﻿package com.shuqi.model.parse.parser;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.Inflater;

import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.shuqi.common.utils.Log4an;
import com.shuqi.interfaces.OnAfterLoadPage;
import com.shuqi.model.bean.BookChapterInfo;
import com.shuqi.model.bean.BookContentInfo;
import com.shuqi.model.parse.BookContentParserBase;

/**
 * 解析UMD文件app
 * 
 * @author Arthur Jin
 */
public class BookContentLocalAppUMDParser extends BookContentParserBase {
    private static final String TAG = "BookContentLocalAppUMDParser";

    /** 每次返回字符数 */
    private final int CONTENT_NUMBER = 10000;
    /** 全部返回还是返回规定字符数的界限 */
    private final int CONTENT_SMALL = 500;
    /** 正文数据块信息 */
    private List<Map<String, String>> mContentList = new ArrayList<Map<String, String>>();
    /** 当前书籍信息 */
    private BookContentInfo mBookContentInfo;
    /** 目录 */
    private List<BookContentInfo> mCurrCatalogList;
    private int mStartIndex;
    /** 当前章缓存 */
    private BookContentInfo currInfo;
    /** 当前章文件名 */
    private String currFileName;

    private int contentStart;

    @Override
    public BookContentInfo getCurInfos(Context context, BookContentInfo params, boolean isNext,
            OnOneChpaterLoadDone callBack) {

        logIndex("next", params.getNextChapter());
        logIndex("pre", params.getPrevChapter());
        logIndex("cur", params.getCurChapter());
        Log.d(TAG, "getCurInfos START ....... ");

        currFileName = params.getFliePath();

        Log4an.i("yjd",
                "currFileName：" + currFileName + " ,cur_index=" + params.getStartIndex());
        mStartIndex = params.getStartIndex();
//        try {
//            Log4an.i(Log4an.TAG_YJD, "params.getStartIndex()=" + params.getStartIndex());
//            mStartIndex = Integer.valueOf(params.getStartIndex());
//        } catch (NumberFormatException e1) {
//            e1.printStackTrace();
//        }

        final boolean fileExists = initBookContentInfo();
        Log4an.i("yjd", "fileExists=" +fileExists);
        if (!fileExists) {
            params.setErrorMessage("文件已删除");
            return null;
        }

        currInfo = getInfo(params, mStartIndex, isNext);

        // Log.d(TAG, "file.exists() : " + "getInfo cur_index : " + cur_index);
        Log4an.i("yjd", "currInfo is null=" + (currInfo==null?true:false));
        if (currInfo != null) {
            currInfo.setEncoding("Unicode");
            if (!TextUtils.isEmpty(mBookContentInfo.getBookname()))
                currInfo.setBookname(mBookContentInfo.getBookname());

            currInfo.setTotalLength(mBookContentInfo.getTotalLength());
        }

        if (currInfo == null || currInfo.getCurChapterBytes() == null) {
            params.setErrorMessage("很抱歉，暂不支持解析该文件");
            params.setPercent1(String.valueOf(0));
        } else {
            params.getPrevChapter().setStartIndex(currInfo.getStartIndex());
            params.getNextChapter().setStartIndex(currInfo.getEndIndex() + 1);
        }

        // Log.d(TAG, "getCurInfos END ....... ");

        return currInfo;
    }

    private void logIndex(String tag, BookChapterInfo chapterInfo) {
//        Log.d(TAG, tag + " startIndex : " + chapterInfo.getStartIndex() + " endIndex : "
//                + chapterInfo.getEndIndex());
    }

    /***
     * 初始化书籍信息
     */
    private boolean initBookContentInfo() {
        // 获取当前包目录和书籍信息
        if (mBookContentInfo == null) {
            File file = new File(currFileName);
            Log.d(TAG, "file.exists() : " + file.exists());
            if (file.exists()) {
                mBookContentInfo = new BookContentInfo();
                mBookContentInfo.setStartIndex(mStartIndex);
                contentStart = 0;
                int length = 0;
                int[] chaptreLocation = null;
                try {
                    FileInputStream fis = new FileInputStream(file);
                    byte[] bs = new byte[4];
                    fis.read(bs);
                    contentStart += 4;
                    if (bs[0] != -119 || bs[1] != -101 || bs[2] != -102 || bs[3] != -34) {
                        Log4an.e("yjd", "this is not a umd file!!!");
                    } else {
                        // 读取标题属性
                        fis.skip(12);
                        contentStart += 12;
                        length = fis.read() - 5;
                        contentStart += 1;
                        mBookContentInfo.setBookname(readInfo(length, fis));
//                        Log.d(TAG, "getBookname=" + mBookContentInfo.getBookname());
                        // 读取作者属性
                        fis.skip(4);
                        contentStart += 4;
                        length = fis.read() - 5;
                        contentStart += 1;
                        mBookContentInfo.setAuthor(readInfo(length, fis));
//                        Log.d(TAG, "getAuthor=" + mBookContentInfo.getAuthor());
                        // 跳过不需要的数据
                        int skipNumber = 0;
                        int tableNumber = 0;
                        while (skipNumber != 1) {
                            while (fis.read() != 35) {
                                contentStart++;
                            }
                            tableNumber = fis.read();
                            if (tableNumber != 131) {
                                if (tableNumber != 11) {
                                    fis.skip(2);
                                    length = fis.read() - 5;
                                    fis.skip(length);
                                    contentStart = contentStart + length + 5;
                                } else { // 获取正文字符数
                                    fis.skip(2);
                                    length = fis.read() - 5;
                                    byte[] totalNumberByte = new byte[4];
                                    fis.read(totalNumberByte);
                                    final int totalNumber = bytesToInt(totalNumberByte);
                                    mBookContentInfo.setTotalLength(totalNumber);
//                                    Log.d(TAG, "getTotalLength=" + mBookContentInfo.getTotalLength());
                                    contentStart += 7;
                                }
                            } else { // 读取章节偏移
                                fis.skip(12);
                                contentStart += 14;

                                // 读取文章偏移数据
                                byte[] pyLength = new byte[4];
                                fis.read(pyLength);
                                contentStart += 4;
                                length = bytesToInt(pyLength) - 9;
                                // this.chapterNumber = length / 4;

                                // 解析章节偏移量,存储在int[] temp中。
                                int[] temp = new int[length / 4];
                                chaptreLocation = new int[length / 4];
                                mCurrCatalogList = new ArrayList<BookContentInfo>();
                                // 章节所属的正文内容数据块的索引
                                int j = 0;
                                for (int i = 0; i < length / 4; i++) {
                                    fis.read(pyLength);
                                    contentStart += 4;
                                    temp[i] = bytesToInt(pyLength);
                                    if (i > 0) {
                                        if (temp[i] < temp[i - 1]) {
                                            j++;
                                        }
                                    }
                                    chaptreLocation[i] = temp[i] + (65535 * j);
                                    // 每章的第一个字在全文中的字符索引
                                    BookContentInfo info = new BookContentInfo();
                                    mCurrCatalogList.add(info);
                                    info.setStartIndex(chaptreLocation[i]);
                                    info.setFliePath(currFileName);
                                }
                                skipNumber = 1;
                            }
                        }
                        // 读取每章标题
                        skipNumber = 0;
                        while (skipNumber != 1) {
                            do {
                                contentStart++;
                            } while (fis.read() != 35);
                            if (fis.read() == 132) {
                                fis.skip(16);
                                contentStart += 16;
                                skipNumber = 1;
                            }
                            contentStart++;
                        }
                        int i = 0;
                        for (int j = 0; j < length / 4; j++) {
                            i = fis.read();
                            contentStart += 1;
                            mCurrCatalogList.get(j).setCurChapterName(readInfo(i, fis));
                        }
                    }
//                    Log.d(TAG, "111111111111111111111111" );
                    // 跳过正文
                    int skipPicture = 0;
                    int number = 0;
                    int dataBlockNumber = 0;
                    int dataLength = 0;
                    boolean contentBlocks = true;
                    int isContentBlock = 0;
                    while (skipPicture != 1) {
                        number = fis.read();
                        if (number == 35) {
                            // 跳过封皮功能块
                            if ((isContentBlock = fis.read()) == 130) {
                                fis.skip(3);
                                fis.skip(4);
                                skipPicture = 1;
                            } else {// 正文结束块
                                if (isContentBlock == 129) {
                                    contentBlocks = false;
                                }
                                fis.skip(2);
                                length = fis.read() - 5;
                                fis.skip(length);
                            }
                        } else {
                            // 正文数据块
                            if (contentBlocks) {
                                fis.skip(4);
                                byte[] temp = new byte[4];
                                fis.read(temp);
                                length = bytesToInt(temp) - 9;
                                byte[] dataBlock = new byte[length];
                                fis.read(dataBlock);
                                byte[] unDataBlock = decompress(dataBlock);
                                Map<String, String> map = new HashMap<String, String>();
                                map.put("id", dataBlockNumber + "");
                                map.put("beginIndex", dataLength + "");
                                dataLength += unDataBlock.length;
                                map.put("endIndex", (dataLength - 1) + "");
                                mContentList.add(map);
                                dataBlockNumber++;
                            } else {
                                fis.skip(4);
                                byte[] temp = new byte[4];
                                fis.read(temp);
                                length = bytesToInt(temp) - 9;
                                fis.skip(length);
                            }
                        }
                    }
                   
                    // 读取封面图
                    // fis.skip(5);
                    // byte[] temp = new byte[4];
                    // fis.read(temp);
                    // length = this.bytesToInt(temp);
                    // byte[] jpg = new byte[length];
                    // fis.read(jpg);
                    // bitmap = BitmapFactory.decodeByteArray(jpg, 0, jpg.length);

                    BookContentInfo info = new BookContentInfo();
                    getContent(info, true, mBookContentInfo.getTotalLength() - 100,
                            mBookContentInfo.getTotalLength());
//                    Log.d(TAG, "222222222222222222222222=="+(info==null?true:false) );
                    if (info != null && !TextUtils.isEmpty(info.getChaptercontent())) {
                        for (int i = info.getChaptercontent().length() - 1; i >= 0; i--) {
                            if (info.getChaptercontent().charAt(i) != '\r'
                                    && info.getChaptercontent().charAt(i) != '\n'
                                    && info.getChaptercontent().charAt(i) != ' '
                                    && info.getChaptercontent().charAt(i) != '　') {
                                mBookContentInfo.setTotalLength(mBookContentInfo.getTotalLength()
                                        - (info.getChaptercontent().length() - 1 - i) * 2);
//                                Log.d(TAG, "3333333333333333333=="+mBookContentInfo.getTotalLength() );
                                break;
                            }
                        }
                    }
//                    Log.d(TAG, "4444444444444444444444" );
                    if (mStartIndex > mBookContentInfo.getTotalLength() - 3) {
                        mStartIndex = (int) mBookContentInfo.getTotalLength() - 3;
                        mBookContentInfo.setStartIndex(mStartIndex);
                    }
//                    Log.d(TAG, "55555555555555555555" );
                    fis.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, "error msg : " + e.getMessage());
                }
            } else {
                Log.d(TAG, "the file is null");
                return false;
            }
        }
//        Log.d(TAG, "66666666666666666666666" );
        return true;
    }

    /**
     * 获取某一章内容
     * 
     * @param startIndex 字索引
     * @param isNext 是否加载的是下一章
     * @return
     */
    public BookContentInfo getInfo(BookContentInfo baseInfo, int startIndex, boolean isNext) {
        BookContentInfo info = null;
        try {
            if (startIndex <= 0 && !isNext) {
                return info;
            } else if (startIndex >= mBookContentInfo.getTotalLength() - 1 && isNext) {
                return info;
            } else if (mBookContentInfo != null) {
                info = baseInfo;
                long beginIndex;
                long endIndex;
                if (isNext) {// 从索引向后读
                    if (info.getStartIndex() == 0 && info.getEndIndex() == 0) {// 从本地书籍初始加载或者从书签加载
                        startIndex = info.getBookmarkByteOffset();
                        startIndex = (startIndex / CONTENT_NUMBER) * CONTENT_NUMBER;
                    }
                    beginIndex = startIndex;
                    if (startIndex + CONTENT_NUMBER + CONTENT_SMALL >= (mBookContentInfo
                            .getTotalLength() - 1)) {
                        endIndex = mBookContentInfo.getTotalLength() - 1;
                    } else {
                        endIndex = startIndex + CONTENT_NUMBER - 1;
                    }
                } else {// 从索引向前读
                    if (startIndex - CONTENT_NUMBER - CONTENT_SMALL <= 0) {
                        beginIndex = 0;
                    } else {
                        beginIndex = startIndex - CONTENT_NUMBER;
                    }
                    endIndex = startIndex - 1;
                }

                getContent(info, isNext, beginIndex, endIndex);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return info;
    }

    @Override
    public BookContentInfo getCurrInfo(Activity context) {
        return currInfo;
    }

    @Override
    public void loadPrevInfo(Activity context, final OnAfterLoadPage onAfterLoadPage,
            BookContentInfo params) {
        synchronized (BookContentLocalAppUMDParser.this) {
            final BookContentInfo info = getCurrInfo(context);
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onAfterLoadPage.runOnUiThread(info);
                }
            });
        }
    }

    @Override
    public void loadNextInfo(Activity context, final OnAfterLoadPage onAfterLoadPage,
            BookContentInfo params) {
        synchronized (BookContentLocalAppUMDParser.this) {
            final BookContentInfo info = getCurrInfo(context);
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onAfterLoadPage.runOnUiThread(info);
                }
            });
        }

    }

    @Override
    public boolean hasPreChapter(int index) {
        if (index > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean hasNextChapter(int index) {
        boolean isHasNext = false;
        if (index < mBookContentInfo.getTotalLength()) {
            if ((index + CONTENT_NUMBER) >= mBookContentInfo.getTotalLength()) {
                if ((mBookContentInfo.getTotalLength() - index < 10)) {
                    isHasNext = false;
                } else {
                    isHasNext = true;
                }
            } else {
                int temp = index + CONTENT_NUMBER;
                if (temp < mBookContentInfo.getTotalLength()
                        && mBookContentInfo.getTotalLength() - temp < 10) {
                    isHasNext = false;
                } else {
                    isHasNext = true;
                }
            }
        } else {
            isHasNext = false;
        }
        return isHasNext;
    }

    public void getContent(BookContentInfo info, boolean isNext, long startContent, long endContent) {
        Log.d(TAG, "isNext="+isNext+",startContent="+startContent+",endContent="+endContent);
        int py = 0;
        int beginBlock = 0;
        int endBlock;
        int length = 0;
        if (startContent < 0) {
            startContent = 0;
        }
        if (endContent > (mBookContentInfo.getTotalLength() - 1)) {
            endContent = mBookContentInfo.getTotalLength() - 1;
        }
        Log.d(TAG, "**endContent="+endContent);
        byte[] content = null;
        byte[] temp;
        byte[] stringByte = new byte[(int) (endContent - startContent + 3)];
        stringByte[0] = (byte) 255;
        stringByte[1] = (byte) 254;
        String stringBegin = null;
        FileInputStream fileInputStream;
        try {
//            Log.d(TAG, "**currFileName="+currFileName);
            fileInputStream = new FileInputStream(currFileName);
            fileInputStream.skip(this.contentStart);

            // 计算起始和结束数据块
            while (Integer.valueOf(mContentList.get(beginBlock).get("endIndex")) < startContent) {
                beginBlock++;
            }
            Log.d(TAG, "beginBlock="+beginBlock);
            endBlock = beginBlock;
            while (Integer.valueOf(mContentList.get(endBlock).get("endIndex")) < endContent) {
                endBlock++;
            }
            Log.d(TAG, "endBlock="+endBlock+",py="+py);
            // 跳到相应数据块，并获取数据
            while (py <= endBlock) {
                Log.d(TAG, "跳到相应数据块，并获取数据");
                // 找到正文数据块
                while (fileInputStream.read() != 36) {
//                    fileInputStream.skip(1);//跳过一个字节
//                    info=null;
//                    return;
                }
                fileInputStream.skip(4);
                byte[] lengthByte = new byte[4];
                fileInputStream.read(lengthByte);
                length = bytesToInt(lengthByte) - 9;
                Log.d(TAG, "1.beginBlock="+beginBlock+",py="+py+",length="+length);
                if (py < beginBlock) {
                    fileInputStream.skip(length);
                } else { // 解压缩并获取内容
                    content = new byte[length];
                    fileInputStream.read(content);
                    temp = decompress(content);
                    int blockBegin = Integer.valueOf(mContentList.get(py).get("beginIndex"));
                    int blockEnd = Integer.valueOf(mContentList.get(py).get("endIndex"));
                    if (py == beginBlock) {
                        if (beginBlock == endBlock) { // 要获取的数据在一个数据块
                            long bigNumber = endContent - startContent + 3;// 在该数据块中要取的字节数
                            long tempIndex = startContent - blockBegin - 2;
                            stringByte[2] = temp[(int) (2 + tempIndex)];
                            for (int i = 3; i < bigNumber; i++) {
                                int temps = (int) (i + tempIndex);
                                if (temp[temps] == 32 && temp[temps - 1] == 41) {// 处理换行
                                    stringByte[i] = 0;
                                    stringByte[i - 1] = 10;
                                } else {
                                    stringByte[i] = temp[temps];
                                }
                            }
                        } else {// 不再一个数据块中
                            long bigNumber = blockEnd - startContent;// 在该数据块中要取的字节数
                            long tempIndex = startContent - blockBegin - 2;
                            stringByte[2] = temp[(int) (2 + tempIndex)];
                            for (int i = 3; i <= bigNumber; i++) {
                                int temps = (int) (i + tempIndex);
                                if (temp[temps] == 32 && temp[temps - 1] == 41) {
                                    stringByte[i] = 0;
                                    stringByte[i - 1] = 10;
                                } else {
                                    stringByte[i] = temp[temps];
                                }
                            }
                        }
                    } else if (py == endBlock) {
                        long bigNumber = endContent - startContent + 3;
                        long tempIndex = startContent - blockBegin - 2;
                        stringByte[(int) (blockBegin - startContent + 2)] =
                                temp[(int) (blockBegin - startContent + 2 + tempIndex)];
                        for (int i = (int) (blockBegin - startContent + 3); i < bigNumber; i++) {
                            int temps = (int) (i + tempIndex);
                            if (temp[temps] == 32 && temp[temps - 1] == 41) {
                                stringByte[i] = 0;
                                stringByte[i - 1] = 10;
                            } else {
                                stringByte[i] = temp[temps];
                            }
                        }
                    } else {
                        long bigNumber = blockEnd - startContent;
                        long tempIndex = startContent - blockBegin - 2;
                        stringByte[(int) (blockBegin - startContent + 2)] =
                                temp[(int) (blockBegin - startContent + 2 + tempIndex)];
                        for (int i = (int) (blockBegin - startContent + 3); i <= bigNumber; i++) {
                            int temps = (int) (i + tempIndex);
                            if (temp[temps] == 32 && temp[temps - 1] == 41) {
                                stringByte[i] = 0;
                                stringByte[i - 1] = 10;
                            } else {
                                stringByte[i] = temp[temps];
                            }
                        }
                    }
                }
                py = py + 1;
            }
            Log.d(TAG, "*******1111************************");
            stringBegin = new String(stringByte, "Unicode");
            int firstParagraph = stringBegin.indexOf("\n");
            int endParagraph = stringBegin.lastIndexOf("\n");
            if (isNext) {// 向后取，末尾取整段
                if (endContent != mBookContentInfo.getTotalLength() - 1) {
                    stringBegin = stringBegin.substring(0, endParagraph + 1);
                    info.setEndIndex((int) (startContent + endParagraph * 2 - 1));
                } else {
                    info.setEndIndex((int) ((endContent - 1)));
                }
                info.setStartIndex((int) (startContent));
            } else { // 向前取，起始取整段
                if (startContent != 0) {
                    stringBegin = stringBegin.substring(firstParagraph + 1);
                    info.setStartIndex((int) (startContent + firstParagraph + 1));
                } else {
                    info.setStartIndex(0);
                }
                info.setEndIndex((int) endContent);

                Log.d(TAG, " stringByte.length :" + stringByte.length + " stringBegin ： "
                        + stringBegin.length() + " info.getStartIndex() : " + info.getStartIndex());

            }
//            Log.d("1", "stringBegin="+stringBegin );
            info.setCurChapterBytes(stringBegin.getBytes("Unicode"));
//            info.setChaptercontent(stringBegin);
            
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "e="+e.toString());
        }
    }

    /**
     * 获得数据长度后，从fis中读取length字节的数据并转换编码格式为UTF-8
     * 
     * @param length
     * @param fis
     * @return
     * @throws IOException
     */
    private String readInfo(int length, FileInputStream fis) throws IOException {
        byte[] bytes;
        byte[] Ibytes;
        String str;

        bytes = new byte[length];
        int n = fis.read(bytes);
        contentStart += length;
        Ibytes = new byte[length + 2];
        Ibytes[0] = (byte) 255;
        Ibytes[1] = (byte) 254;
        System.arraycopy(bytes, 0, Ibytes, 2, bytes.length);
        str = new String(Ibytes, "Unicode");
        str = new String(str.getBytes(), "UTF-8");
        if (n > 0) {
            return str;
        }
        return str;
    }

    /**
     * 将byte[]转换为int
     * 
     * @param bytes
     * @return
     */
    public static int bytesToInt(byte[] bytes) {
        int num = bytes[0] & 0xFF;
        num |= ((bytes[1] << 8) & 0xFF00);
        num |= ((bytes[2] << 16) & 0xFF0000);
        num |= ((bytes[3] << 24) & 0xFF000000);
        return num;
    }

    /** 对ZLIB格式文本进行解压缩，得到byte[] */
    public static byte[] decompress(byte[] data) {
        byte[] output = null;
        Inflater decompresser = new Inflater();
        decompresser.reset();
        decompresser.setInput(data);
        ByteArrayOutputStream o = new ByteArrayOutputStream();
        try {
            byte[] buf = new byte[1024];
            while ((decompresser.inflate(buf)) != 0) {
                o.write(buf);
            }
            output = o.toByteArray();
        } catch (Exception e) {
            output = data;
            e.printStackTrace();
        } finally {
            try {
                o.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        decompresser.end();
        return output;
    }

    @Override
    public List<BookContentInfo> getBookCatalogList() {
        return mCurrCatalogList;
    }

    @Override
    public boolean isPageFetching() {
        // TODO Auto-generated method stub
        return false;
    }
}
